package tij4.concurrent.source;

import java.sql.Time;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/*
    使用显示的Lock和Condition对象
    signalAll()比notifyAll()更安全
    使用互斥并允许任务挂起的基本类是Condition
 */
class Car2 {
    private ReentrantLock reentrantLock = new ReentrantLock();
    private Condition condition = reentrantLock.newCondition();
    private boolean waxOn = false;      //wax 蜡,是否打蜡

    public void waxed() {
        reentrantLock.lock();
        try {
            waxOn = true;
            condition.signalAll();
        }finally {
            reentrantLock.unlock();
        }
    }

    public void buffed() {  // buffed 磨光,抛光
        reentrantLock.lock();
        try {
            waxOn = false;
            condition.signalAll();
        }finally {
            reentrantLock.unlock();
        }
    }
    public void waitForWaxing() throws InterruptedException {
        reentrantLock.lock();
        try {
            while (waxOn == false) {
                condition.await();
            }
        }finally {
            reentrantLock.unlock();
        }
    }
    public void waitForBuffing() throws InterruptedException {
        reentrantLock.lock();
        try {
            while (waxOn == true) {
                condition.await();
            }
        }finally {
            reentrantLock.unlock();
        }
    }
}

class WaxOn2 implements Runnable {
    private Car2 car2;

    public WaxOn2(Car2 car2) {
        this.car2 = car2;
    }

    @Override
    public void run() {
        try {
            while (!Thread.interrupted()) {
                System.out.println("Wax On");
                TimeUnit.MILLISECONDS.sleep(100);
                car2.waxed();
                car2.waitForBuffing();
            }
        }catch (InterruptedException e) {
            System.out.println("Exiting via interrup");
        }
        System.out.println("Ending Wax On task");
    }
}

class WaxOff2 implements Runnable {
    private Car2 car2;

    public WaxOff2(Car2 car2) {
        this.car2 = car2;
    }

    @Override
    public void run() {
       try {
           while (!Thread.interrupted()) {
               car2.waitForWaxing();
               System.out.println("Wax Off!");
               TimeUnit.MILLISECONDS.sleep(100);
               car2.buffed();
           }
       }catch (InterruptedException e) {
           System.out.println("Exiting via interrupt");
       }
        System.out.println("Ending WaxOff task");
    }
}
public class WaxOMatic2 {
    public static void main(String[] args) throws Exception{
        Car2 car2 = new Car2();
        ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.execute(new WaxOff2(car2));
        executorService.execute(new WaxOn2(car2));
        TimeUnit.SECONDS.sleep(5);
        executorService.shutdownNow();


    }
}
